1주차 - istio 소개, 첫걸음

개요

로컬에서 컨트롤러 개발 편하게 하려면 kind를 쓰는 게 좋긴 할 것 같다.

나는 최신 쿠버네티스 버전을 사용하려고 한다.
이유는 다음과 같다.
일단 가장 우선하는 이유로.. 교육을 듣는 게 아니라 스터디를 하는 입장에서 그냥 따라만 하는 것은 내 적성에 안 맞는다.
image.png
두번째 이유는 쿠버네티스와 비슷하게 이스티오의 지원 주기가 길지 않기에 결국 버전을 열심히 쫓아가야 하는 클러스터 환경에서 최신 버전을 사용하는 것이 유리하기 때문이다.[1]
이스티오는 대략 분기 당 한번씩 마이너 버전을 배포하며, n 버전은 n+2 버전이 배포된 이후 6주까지만 지원된다.
위 그림을 보면, 1.25 버전이 배포된 3월로부터 6주가 지난 4월 중반에 1.23 버전의 지원이 종료되는 것을 확인할 수 있다.
(쿠버보다 더 박한 것 같기도..)
책에서 사용하는 버전은 현재 기준으로 매우 옛날이며 최신 기술을 학습하는데 있어 아쉬움이 있을 것이라 생각했고, 이에 내가 진행하는 실습에서는 가급적 최신 버전을 고수하기로 했다.
도중에 S-테라폼으로 헬름 설치할 때 네임스페이스 이슈를 파보았다.

기본 설치

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  profile: demo
  components:
    ingressGateways:
    - name: istio-ingressgateway
      enabled: true
      k8s:
        service:
          type: NodePort
          ports:
          - port: 80
            targetPort: 8080
            nodePort: 30000
          externalTrafficPolicy: Local
    egressGateways:
    - name: istio-egressgateway
      enabled: false
  meshConfig:
    defaultProviders:
      metrics:
      - prometheus
      tracing:
      - jaeger

기본적인 세팅은 이렇게 했다.
istioctl을 활용하면 이렇게 기본적인 설정들을 이스티오 오퍼레이터 양식 파일을 통해 진행할 수 있다.
이전 버전에서 demo 프로필은 트레이싱을 자동으로 jaeger로 설정했던 모양이다.
그러나 최신 버전의 demo 프로필의 경우 왜인지는 모르겠으나 tracing 필드가 비워진 채로 세팅이 되기 때문에, 명시적으로 meshConfig 필드에 jaeger를 세팅해줘야만 한다.
(나는 이걸 몰라서 다시 세팅을 했는데, 아래 명령어를 다시 입력하는 것만으로 인플레이스 반영이 됐다.)

istioctl install -f initstio.yaml -y

image.png
설치 자체는 매우 간단하게 이뤄진다.

kubectl get all,svc,ep,sa,cm,secret,pdb -n istio-system 

image.png
굉장히 많은 것들이 설치된 것을 확인할 수 있다.
워크로드만 따지자면, 데모 프로필로 설치된 컴포넌트는 컨트롤 플레인에 해당하는 istiod와 이스티오 인그레스 게이트웨이이다.
image.png
istiod의 포트가 상당히 많길래 봤는데, 다음과 같이 엔보이와 통신할 때 쓰일 포트와 디버그, 모니터링 등을 위한 포트가 설정돼있는 것을 확인할 수 있다.

관측 가능성 세팅

image.png
이스티오에서 제공하는 모니터링 툴들은 istioctl을 설치할 때 받은 samples/addons 디렉에 들어있다.
image.png
스터디 실습 상에서 각 모니터링 툴은 30001부터 30004로 세팅하도록 하고 있는데, 처음 kind 클러스터를 만들 때도 포트 매핑을 이쪽에 해뒀으므로 이에 맞춰서 세팅을 진행하면 내 로컬 호스트 환경에서 쉽게 브라우저로 ui 접근이 가능해진다.
image.png
나는 배포 후 설정하는 과정을 최소화하기 위해 일찌감치 양식 파일에서 서비스에 노드포트 설정을 넣어주었다.
image.png
트레이싱 도구로는 jaeger가 사용되는데 서비스 이름은 tracing이니 유의하자.
jaeger.yaml 파일을 열어서 서비스 부분을 고쳐주면 된다.
image.png
image.png
localhost로 각 포트에 들어가보면 모니터링 툴들이 배포된 것을 확인할 수 있다.

샘플 어플리케이션 배포

kubectl label namespace default istio-injection=enabled

먼저 데이터 플레인에 사이드카가 주입될 수 있도록 네임스페이스에 라벨을 달아준다.
image.png
이 설정은 승인 웹훅을 발동시키는데, 이 중에서 위의 리소스를 발동시킨다.
image.png
이름 때문에 당연히 istio-sidecar-injector가 작동하는 줄 알았으나, 무슨 연유에선지 해당 리소스는 그냥 사용이 되지 않도록 설정돼있다.
image.png
대신 istio-revision-tag-default 리소스를 보면 이렇게 네임스페이스의 라벨에 따라 웹훅이 발동되도록 설정이 돼있는 것을 확인할 수 있다.
내 생각에는 아마 rev 관련 변형 승인 웹훅까지 추가되면서 한 리소스로 모든 웹훅을 관리하기 위한 변화과정이 아닐까 한다.

image.png
아무튼 샘플로 주어진 예제를 실행한다.
예제가 무척 많기 때문에, 각각 어떤 예제인지 확인하면서 진행하는 것도 실습에 도움이 될 것 같다.
image.png
여러 개의 파드가 사이드카가 주입된 채 실행된다.

kubectl port-forward deployment/productpage-v1 15000:15000

15000 포트로 엔보이의 관리자 페이지가 노출되고 있으므로, 해당 포트를 포워딩하면 관리자 페이지에 들어가볼 수 있다.
image.png
물론 이렇게 일일히 엔보이를 세팅하는 건 안티 패턴이고, 현재 설정이 어떻게 돼있는지를 알아볼 때도 그냥 istio의 자체 기능을 활용하는 것이 나을 것이다.
다만 조금 더 딮하게 파보고 싶다면 이런 영역도 있다~ 정도?

이스티오 리소스를 통한 트래픽 노출

이스티오를 설치할 때 인그레스 게이트웨이를 설치하여 외부에서 클러스터로 접속이 가능한 게이트웨이를 뚫었다.
이 게이트웨이를 사용할 때, 이스티오로부터 비롯된 게이트웨이API를 쓰는 것도 가능하다.
그러나 일단 먼저 기본적인 이스티오의 리소스를 사용해본다.

apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 8080
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: bookinfo
spec:
  hosts:
  - "*"
  gateways:
  - bookinfo-gateway
  http:
  - match:
    - uri:
        exact: /productpage
    - uri:
        prefix: /static
    - uri:
        exact: /login
    - uri:
        exact: /logout
    - uri:
        prefix: /api/v1/products
    route:
    - destination:
        host: productpage
        port:
          number: 9080

각 리소스가 무엇인지 명확하게 분석하는 것은 이후 주차로 미루겠다.
다만 대충 봐도 쿠버의 기본 인그레스, 서비스를 사용하는 방식이랑 상당히 비슷한 것은 확인할 수 있을 것이다.
나중에 볼 게이트웨이api와는 더 비슷하게 느껴질 것이다.

k -n istio-system get svc istio-ingressgateway -oyaml | yh

image.png
간단하게만 말하자면 인그레스 게이트웨이 엔보이가 현재 배포돼있는 상태로 여기에서 외부 트래픽을 수신할 수 있다.
이를 게이트웨이 리소스로 추적하여 이스티오 서비스 레지스트리에 넣어두는 작업을 한다.
이후에는 가상 서비스 리소스를 이용해 인그레스마냥 엔드포인트 조건에 부합하는 모든 트래픽을 특정 서비스로 라우팅하는 규칙을 기입하여 적용한 것이다.
image.png
결과적으로 실제 트래픽은 이 친구가 받게 될 것이다.

containers:
  - image: docker.io/istio/examples-bookinfo-productpage-v1:1.20.2
    name: productpage
    ports:
    - containerPort: 9080
      protocol: TCP
  - args:
    - proxy
    - sidecar
    - --domain
    - $(POD_NAMESPACE).svc.cluster.local
    - --proxyLogLevel=warning
    - --proxyComponentLogLevel=misc:error
    - --log_output_level=default:info
    image: docker.io/istio/proxyv2:1.25.1
    name: istio-proxy
    ports:
    - containerPort: 15090
      name: http-envoy-prom
      protocol: TCP
    resources:
      limits:
        cpu: "2"
        memory: 1Gi
      requests:
        cpu: 10m
        memory: 40Mi
  initContainers:
  - args:
    - istio-iptables
    - -p
    - "15001"
    - -z
    - "15006"
    - -u 
    - "1337"
    - -m
    - REDIRECT
    - -i
    - '*'
    - -x
    - ""
    - -b
    - '*'
    - -d
    - 15090,15021,15020
    - --log_output_level=default:info
    image: docker.io/istio/proxyv2:1.25.1
    name: istio-init

(마운팅이랑 환경 변수 개수가 너무 많아서 편집했다)
간단하게 실제 트래픽을 받을 파드를 살펴본다.
사이드카 모드이기 때문에 알아서 컨테이너가 추가됐는데, 첫번째는 기본 iptable 세팅을 담당하는 초기화 컨테이너, 그리고 사이드카로 동작할 istio-proxy 컨테이너가 들어갔다.
image.png
맛보기로 해보는 거니 간단하게만 보는 건데 역시 궁금해서 조금 검색해봤다.
초기화 컨테이너에서는 정말 모든 트래픽을 곧이곧대로 엔보이 프록시로 보내버리도록 설정돼있다.

다시 배포한 리소스로 돌아가자.
image.png
간단하게 만들어진 리소스들을 확인할 수 있다.

istioctl proxy-status

image.png
엔보이가 설정에 맞게 제대로 배포됐는지 체크할 때 쓰는 명령어이다.
제대로 동기화된 것을 확인할 수 있다.
참고로 proxy-status의 약자는 ps이다.

istioctl pc all productpage-v1-d49bb79b4-vpmkh

pc는 proxy-config의 약자로 특정 파드의 엔보이에 설정된 정보들을 확인하는 명령어이다.
단순하게 all로 찍으면 매우 많은 정보들이 표시된다.
image.png
image.png
라우팅 규칙이나 리스너에 암호화 통신을 위한 인증서 정보도 확인할 수 있다.

image.png
페이지가 정상적으로 열리는 것을 확인할 수 있다.
image.png
프록시의 로그에 접속 정보가 남는 것을 확인할 수 있다.
이제 구체적으로 어떻게 로컬 환경에서 클러스터의 서비스에 접근할 수 있었는지 시각적으로 확인해보자.

키알리 확인

while true; do curl -s http://127.0.0.1:30000/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 1; done
while true; do curl -s http://127.0.0.1:30000/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 0.5; done
while true; do curl -s http://127.0.0.1:30000/productpage | grep -o "<title>.*</title>" ; echo "--------------" ; sleep 0.1; done

트레이싱과 실시간 메트릭 흐름을 추적하기 위해 먼저 지속적으로 트래픽을 유발시킨다.
키알리의 경우 최근의 트래픽을 모니터링하는 도구이기 때문에 트래픽이 발생하지 않으면 제대로 시각화를 하기 어렵다.
image.png
트래픽 그래프 탭에 들어와서 시각화 표시에 각종 세팅을 넣어준다.
꼭 해야 한다 이런 건 없지만, 세팅할수록 이뻐진다..!
추가적으로 넣어준 시각화 세팅은 다음과 같다.

image.png
이렇게 하면 실시간으로 트래픽이 전송되는 것을 시각적으로 확인할 수 있게 된다!
(근데 간단한 샘플인데도 생각보다 렉이 조금.. 있다..)
versioned app graph를 사용했는데, 서비스만 보거나 워크로드만 보는 식으로 커스텀도 가능하다.
앞서 미리 샘플 어플리케이션을 분석하지 않았는데, 이렇게 키알리만으로 쉽게 파악이 가능하기 때문이다.

먼저 전체 구조를 보자면 4개의 어플리케이션이 있다.
메인 web ui는 productpage에서 제공하며, 뒷단에 WAS로 detail과 review가 존재한다.
이때 review의 경우 세 개의 파드가 배포돼있는 상태(각각 디플로이먼트가 돼있음)로 2,3버전부터 rating으로부터 별점 정보까지 가져온다.
image.png
리뷰 쪽에 각 다른 버전들이 있기 때문에, 실제로도 새로고침을 계속 해주면 평점이 생겼다 없어졌다 한다.
image.png
참고로 검은 색깔은 버전 2, 빨간 색깔이 버전 3이다.

image.png
트래픽의 흐름으로 보자면, 먼저 로컬에서 반복문으로 돌리고 있는 요청은 인그레스 게이트웨이를 타고 productpage 서비스에 먼저 전해진다.
이쪽으로 전달되는 이유는 virtual service에 라우팅 규칙이 세팅돼있기 때문이다.
그럼 해당 서비스의 엔드포인트로 실제 트래픽이 전달되고, 여기에서 다시 detail과 review로 추가 요청이 날아가는 방식이다.
image.png
실제 트래픽을 받는 대상들만 명확히 하고자 service nodes는 시각화에서 제외시켰다.
어차피 서비스는 셀렉터에 맞게 엔드포인트를 업데이트하는 역할만 하기 때문에 트래픽의 흐름만 명확하게 보고 싶다면 서비스 객체를 안 보는 것도 좋은 선택지 같다.
image.png
트래픽 분산 비율을 볼 때 주의점이 조금 있다.
키알리는 각 워크로드의 엔보이가 노출하는 프로메테우스 메트릭을 기반으로 보기 좋게 시각화해주는 툴이다.
메트릭에 표시된 정보에 따라서 각종 정보를 계산해 보여줄 뿐이므로, 이 비율을 곧이곧대로 받아들이면 곤란하다.
현재 샘플 어플리케이션은 productpage에서 review와 detail에 각각 한번씩 api 요청을 날리는데 이것은 매 요청마다 각각 이뤄지는 것이지, 분산하여 트래픽을 보내는 것이 아니다(빨간색).
반면 review 서비스에서 3개의 엔드포인트 파드에 트래픽을 보내는 것은 실제로 iptables 규칙에 따라 트래픽이 분산되는 것이 맞다(파란색).
간단하게만 정리하자면,

이런 식으로 이해해야 명확하게 비율을 파악할 수 있다.

image.png
다음으로 옆의 탭들을 둘러본다.
워크로드 탭에 내가 배포한 디버그용 파드에 missing app이라고 표시되는 것이 보인다.
워크로드에 app: {앱}, version: {버전} 라벨을 달아두어야 키알리에서 명확하게 어플리케이션으로서 인식하고 시각화를 해주기 때문에 비즈니스 로직이 들어가는 워크로드의 경우 각 라벨을 설정해주는 게 좋다.
image.png
서비스 탭에 들어가보면 각 서비스들이 보인다.
productpage의 경우 게이트웨이와 직접적으로 연결되며 virtual service의 대상으로 설정돼있기에 세부정보가 표시된다.
kubernetes 서비스의 경우 트래픽이 한번도 발생하지 않았기 때문에 헬스 상태가 표시되지 않는 것도 확인할 수 있다.
image.png
마지막으로 mesh 탭에 들어가면 현재 이스티오 관련 설정된 전체 구조 정보를 확인할 수 있다.
아직 명확하게 파악을 못한 지점 중 하나는 예거가 표시되지 않는다는 것.
이 문서를 봤을 때, 귀찮지만 추가적인 세팅을 할 필요가 있어 보인다.[2]
근데.. 어떻게 세팅해야 할 지는 아직 잘 모르겠다.
스터디를 하면서 더 파보도록 하자.

키알리 예거 연동

image.png
키알리에서 istiod의 정보를 확인해보면 배포된 설정 파일을 확인할 수 있는데, 여기에 jaeger가 extentionProvider 필드에 있고, 그래서 defaultProvider 필드에 이 이름을 명시할 수 있다.
(istioctl 암만 봐도 현재 istio의 상태를 파악하는 명령이 없는 것 같아서 키알리로 보는 중..)
다른 세팅으로 잠시 해본다.[3]
아무래도 최신 버전에서는 istioctl이 아니라 텔레메트리 리소스를 따로 등록해서 사용하는 방식으로 세팅하는 게 아닌가 한다.
일단 istiooperator 양식에서 meshconfig 필드에 tracing을 명시적으로 비운다.

apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
  name: mesh-default
  namespace: istio-system
spec:
  tracing:
  - providers:
    - name: jaeger

그 다음 이렇게 Telemetry 리소스를 만든다.
세팅을 해도 변화가 없어서 아예 istioㅇ를 밀고 다시 진행해봤으나, 결과는 변함이 없었다.
일단 jaeger 자체는 정상 동작을 하나, kiali와의 연동은 실패한 채로 이번 실습은 마쳐야할 것 같다.
image.png
뭔가 단서를 찾은 것 같다.[4]
image.png
하하.. 해냈다..

    external_services:
      custom_dashboards:
        enabled: true
      istio:
        root_namespace: istio-system
      tracing:
        enabled: true
        internal_url: "http://tracing.istio-system:16685/jaeger"

키알리 configmap에 세팅 파일이 들어있는데, 여기에 tracing 필드가 비활성화돼있어서 이걸 고쳐주었다..
최신 문서에 이런 말 없었잖아요 ㅠㅜ

image.png
워크로드에 들어가보면 이렇게 트레이싱 정보도 확인할 수 있다.
image.png
참고로 워크로드에서는 이렇게 컨테이너의 로깅 정보도 확인할 수 있다.
image.png
인그레스 게이트웨이도 워크로드로서 추적이 되기 때문에 로그를 받아볼 수 있다.

kubectl exec -it deploy/istio-ingressgateway -n istio-system -- curl -X POST http://localhost:15000/logging?http=debug

로깅 설정을 동적으로 수정해보자.
그냥 /logging으로 요청을 보내면 어떤 것들에 대해 로깅 설정을 할 수 있는지 정보가 나온다.
image.png
디버그 레벨로 로깅 설정을 하자 훨씬 자세하게 정보를 볼 수 있다.

예거 확인

이제 트레이싱 영역을 조금 더 파보자.
image.png
예거가 제대로 세팅됐다면 위와 같이 서비스 단위로 트래픽을 추적할 수 있게 된다.
image.png
어떤 단위로 트레이스를 찾던, 스팬으로 묶인 트레이스들이 나오게 되니 자신이 명확하게 짚을 수 있는 서비스를 골라 찾아보면 된다.
image.png
하나의 트레이스를 골라서 분석해본다.
이 정보로부터 확언할 수는 없지만, productpage로의 요청으로 인해 발생하는 detail과 review에 대한 요청은 동기적으로 이뤄질 가능성이 높다.
만약 비동기적으로 요청을 보내는 방식이었다면 하위 스팬이 겹쳐서 나타나거나, 발생 간격이 매우 짧았을 가능성이 높다.
아무튼 api 요청 중에서는 review에 대한 요청이 상당히 긴 것을 확인할 수 있다.
image.png
각각의 스팬을 뜯어보면 OTel 기반으로 트레이싱을 하는 것으로 보인다.
image.png
실제로도 스팬을 자세히 보면 요청을 받았으면서도 자신도 요청을 보내게 되는 productpage의 경우 client와 server 두 가지 유형의 span을 가지고 있어서 트레이스의 깊이가 더 깊어지는 것을 볼 수 있다.
image.png
이밖에도 다양한 방식으로 트레이스를 분석할 수 있다.
image.png
참고로 위 그래프는 이런 식으로 보면 된다.
productpage가 요청을 처리한 전체 시간 중, 자기 자신이 실제로 할애한 처리시간을 절반 정도를 차지한다.

그라파나 확인

마지막으로 프로메테우스 그라파나까지 보려고 했으나, 솔직히 아직 어떤 메트릭이 중요한지 명확하게 판단을 못하겠어서 내용 정리를 하면서까지 실습하진 않는다.
image.png
음 이런 게 있구나..
컨트롤 플레인 메트릭에 전체 워크로드 트래픽 성공률 등의 지표가 대시보드에 있다.

에러 발생시키기

지금까지 이스티오에서 예제로 제공해준 bookInfo를 이용해서 실습을 진행했다.
책에서는 독자적인 예제로 랜덤하게 에러를 발생시킨 후 재시도 횟수를 늘려 성공률을 높이는 실습을 보여주는데, 이스티오 문서 상에서 bookInfo 실습 관련 글과, 예제 양식 파일을 봤을 때는 비슷하게 실습할 수 있는 설정이 없었다.
bookInfo에서 진행할 수 있는 에러 주입 관련 실습은 다음과 같은 방식이다.

그러나 직접적으로 소스 코드를 파보니 애플리케이션 단에서 에러를 발생시킬 수 있는 설정을 찾을 수 있었다.[5]
문서를 조금 더 제대로 뒤져보면 관련한 부분이 나올지도 모르겠다.
image.png
rating 어플리케이션에 환경 변수 설정을 통해 데이터소스로 mysql이나 몽고 db를 사용할 수 있도록 돼있다.
근데 여기에 추가적으로 에러를 발생시킬 수 있도록 코드가 세팅돼있다.
그래서 파드 환경 변수로 특정 값을 설정하여 에러를 확률적으로 발생시키는 것이 가능하다.
이를 활용해 책의 예제와 비슷하게, 재시도 횟수를 늘리는 것만으로 성공률을 높이는 실습을 해보겠다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ratings-v1
  labels:
    app: ratings
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ratings
      version: v1
  template:
    metadata:
      labels:
        app: ratings
        version: v1
    spec:
      serviceAccountName: bookinfo-ratings
      containers:
      - name: ratings
        image: docker.io/istio/examples-bookinfo-ratings-v1:1.20.2
        imagePullPolicy: IfNotPresent
        env:
          - name: SERVICE_VERSION
            value: v-faulty
        ports:
        - containerPort: 9080

일단 에러를 발생하게 하는 것은 간단하다.
rating 디플로이먼트에서 컨테이너에 환경 변수로 SERVICE_VERSION을 세팅해주기만 하면 끝이다.
에러 상황과 관련한 값들은 다음의 것들이 있다.

v1, v2 같은 값을 세팅하면 mysql과 mongodb를 데이터 소스로 두는 설정이 된다.
image.png
보다시피 ratings에서 50퍼센트 확률로 에러가 발생 중이다.

apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - retries:
      attempts: 5
      perTryTimeout: 7s
      retryOn: 5xx
    route:
      - destination:
          host: ratings

ratings에 재시도 설정을 넣어주었다.
참고로 아무 설정을 하지 않으면 클러스터 전역 설정으로 재시도를 하게 되는데 재시도는 2회, 재시도 발동 조건은 500에러나 커넥션 닫힘 등이 세팅된다.
image.png
근데 아무리 기다리고, 재시도 횟수를 20회로 높이기까지 했는데도 에러율에 변화가 없다..
50퍼센트 확률로 실패하는 서버에 5번의 재시도를 하게 된다면 최종 실패 확률은 1/32인데, 아무리 기다려도 그 정도의 에러율로 내려가지 않는다.
image.png
하도 이상해서 로그를 뜯어봤는데, 로그 상에서는 재시도 횟수가 제대로 반영이 된 마냥 200이 잘 뜨고 있다.
image.png
정말 간혹 가다 503에러가 뜨는 것을 확인할 수 있다.
image.png
옆에 나오는 값으로 봐서도 에러율이 현저하게 줄어든 것이 제대로 표시된다.
사실 아직 명확하게 왜 이렇게 표시가 되는지는 모르겠다.
image.png
다만 예거로 확인해봤을 때, 에러로 표시되는 요청들 중 상당 수는 여러 재시도를 거쳐서 결국 성공한 트레이스라는 것을 확인할 수 있었다.
즉, 키알리에서 표시하는 에러율은 그저 트래픽이 전송 과정 상에서 에러가 한번이라도 발생했을 때 에러로 표시하고 있기에 변화가 없는 것처럼 보였다는 것이다.
생각으로는 키알리에 예거를 연동하지 않아야 오히려 내가 생각하는 에러율 표기가 이뤄질 것 같다.
아니면 프로메테우스 메트릭에 대한 수정이 필요할 수도 있겠다.
image.png
그라파나로는, 내가 하도 이상하다 이상하다 하면서 해당 설정을 지웠다 말았다 하던 순간에만 에러율이 잠깐 오르고, 정직하게 에러율을 표시해주고 있다.
그럼 메트릭 이슈도 아닌 것 같은데..
아무래도 시각화에 대한 이슈는 추가적인 공부가 필요해보인다.
일단 실제 트래픽 장애율이 줄어드는 것은 확인했으니 이스티오의 기본 실습 코드에 대한 테스트는 마치고자 한다.

게이트웨이 api 활용

이스티오가 기본적으로 제공하는 리소스 말고도 최근에는 Gateway API를 통한 리소스 정의도 가능하다.
실제 istiod가 데이터 플레인을 조작하고 설정하는 방식은 비슷할 것으로 생각되고, 다만 설정하는 방식에 대해 조금의 차이는 존재한다.
그래서 이번에는 이 api를 활용해보는 실습을 진행한다.
게이트웨이 api는 인그레스를 대체하는 api로서 개발되고 있으며 cka 시험 범위에도 들어가는 만큼, 결국 알아두면 도움이 될 거라는 것이 내 생각이다.
참고로 referencegrants의 경우 스토리지 관련 세팅에서 댜른 네임스페이스 간 안전하게 리소스를 공유하는 데에도 활용될 만큼 점차 활용도가 높아지고 있다.

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  profile: demo
  components:
    ingressGateways:
    - name: istio-ingressgateway
      enabled: false
      k8s:
        service:
          type: NodePort
          ports:
          - port: 80
            targetPort: 8080
            nodePort: 30000
          externalTrafficPolicy: Local
    egressGateways:
    - name: istio-egressgateway
      enabled: false
  meshConfig:
    defaultProviders:
      metrics:
      - prometheus
      tracing: []

게이트웨이 api에 대한 예제는 공식 문서에서 친절하게 제공되고 있다.[6]
일단 게이트웨이의 리소스들을 써야 하니 istio의 ingress gateway도 비활성화시킨 채로 설치한다.

kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
{ kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.2.1" | kubectl apply -f -; }

그 다음 게이트웨이 crd를 설치해준다.
위 명령어는 이미 crd가 있으면 건너뛰고, 없을 경우에만 공식 레포에서 설치를 진행하는 명령어이다.
image.png
요로코롬 설치가 됐다면 성공.

k get gatewayclass

게이트웨이 api에서 인프라 레벨 관리 역할 리소스를 확인해본다.

apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: istio
spec:
  controllerName: istio.io/gateway-controller
  description: The default Istio GatewayClass

istiod는 gateway api crd가 세팅되면 이를 확인하고 알아서 gatewayclass를 만들어준다.

kubectl label namespace default istio-injection=enabled
kubectl apply -f bookinfo.yaml

이건 다시 언급하진 않겠다.
bookinfo 예제를 다시 배포한다.

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  gatewayClassName: istio
  listeners:
    - name: http
      port: 80
      protocol: HTTP
      allowedRoutes:
        namespaces:
          from: Same
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: bookinfo
spec:
  parentRefs:
    - name: bookinfo-gateway
  rules:
    - matches:
        - path:
            type: Exact
            value: /productpage
        - path:
            type: PathPrefix
            value: /static
        - path:
            type: Exact
            value: /login
        - path:
            type: Exact
            value: /logout
        - path:
            type: PathPrefix
            value: /api/v1/products
      backendRefs:
        - name: productpage
          port: 9080

이제 gateway, route 리소스를 만든다.
실질적인 생김새가 istio의 gateway, virtualservice의 양식과 상당히 비슷한 것을 볼 수 있다.
gateway 리소스의 listeners필드만 잠시 보자면, 이 부분은 어떤 트래픽을 받을지, 그리고 이렇게 열린 게이트웨이에 연결될 수 있는 route 리소스는 어떤 것이 가능한지 지정할 수 있다.

# 모든 네임스페이스의 라우트 허용
      allowedRoutes:
        namespaces:
          from: ALL
---
# 셀렉팅된 네임스페이스만 허용
      allowedRoutes:
        namespaces:
          from: Selector
        selector:
          kubernetes.io/name: test

allowedRoutes 필드의 경우 어떤 네임스페이스의 route 리소스를 허용할지 지정한다.
기본은 같은 네임스페이스의 리소스만 허용하는데, 위처럼 모든 네임스페이스나 특정 네임스페이스들만 허용하는 것도 가능하다.
image.png
성공적으로 두 리소스가 세팅됐다.
image.png
gateway 리소스는 인그레스 컨트롤러를 세팅할 때와 마찬가지로 만들어지면 인그레스 트래픽을 담당할 서비스가 만들어지는데, 기본적으로는 로드밸런서 타입으로 만들어진다.
현 실습에서는 로드밸런서 유형을 사용할 수 없으므로 이걸 cluster ip로 바꿔주겠다.

kubectl annotate gateway bookinfo-gateway networking.istio.io/service-type=ClusterIP --namespace=default

gateway에 어노테이션으로 서비스 유형을 지정해준다.
image.png
그러면 gateway 리소스가 주소를 할당받고 programmed 상태가 된다.

kubectl port-forward svc/bookinfo-gateway-istio 8080:80

이번에도 노드포트를 미리 세팅하는 설정을 하고 싶었는데, 문서를 찾아봤을 때 이걸 미리 세팅할 수 있는 방법은 없는 것 같았다.
서비스 타입을 노트포트로 세팅을 하는 건 가능한데, 어떤 포트를 사용할지 지정하는 필드가 없다.
아쉬운 대로 그냥 포트포워딩으로 실습을 진행한다.
image.png
제대로 들어와진다!

while true; do curl   -s http://127.0.0.1:8080/productpage | grep -o "<title>.*</title>" ; sleep 1; done

실시간 트래픽 확인을 위해 이번에도 반복문을 세팅한다.
image.png
에러 내는 실습 예제를 그대로 적용해서 에러가 나고 있긴 한데, 아무튼 똑같이 세팅되는 것을 확인할 수 있다.
image.png
config 탭에 들어가면 위와 같이 gateway api의 리소스들이 추적되는 것을 확인할 수 있다.

에러율 줄이기 - 첫 시도 실패

kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/experimental-install.yaml

게이트웨이 api에도 재시도 설정 필드가 있긴 한데, 이것은 아직까진 실험적 버전에서만 가능하다.
가능한 이스티오에서 진행한 실습을 전부 진행하고 싶어 추가적으로 실험 버전으로 다시 crd를 수정했다.[7]
기본적으로 gateway api는 클러스터 외부와 내부를 잇는 north-south 트래픽을 관리하기 위한 리소스들이 정의돼있다.
그러나 서비스 메시와 같이 east-west의 트래픽을 조절하기 위해서는 GAMMA Initiative 프로젝트에서 진행 중인 기능을 사용해야 한다.[8]
Gateway Api for Mesh Management and Administration은 2022년부터 생긴 서브 프로젝트로 gateway api를 클러스터 내부의 트래픽을 조절하는데 사용하기 위한 기능 개발 목적을 가지고 있는 작업을 진행하고 있다.
글을 계속 봤을 때는 기본적으로 다른 네임스페이스 간 라우트를 통제하는 것에 주안점을 두고 있는 것으로 보인다.
productor, consumer 라우트를 구분하는 기준이 네임스페이스던데, 아직 이 부분은 명쾌하게 정리가 이뤄지지 않은 듯한 느낌을 받았다.

일단 결론부터 말하자면 이걸 실습하는 것은 실패했다.

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: ratings
spec:
  parentRefs:
    - name: ratings
      kind: Service
      group: core
      port: 9080
  rules:
    - name: retry
      matches:
        - path:
            type: PathPrefix
            value: /ratings
      retry:
        attempts: 5
        codes:
          - 503
          - 501
      backendRefs:
        - name: ratings
          port: 9080

GAMMA 설정 방식 자체는 간단하다.
그냥 parentRefs 필드를 gateway가 아니라 서비스로 지정을 해주면 된다.
그럼 해당 서비스로 들어가는 트래픽에 대해서 매칭되는 트래픽에 대해서 해당 룰이 적용된다고 나와있다.
image.png
이렇게 키알리 서비스 탭에서 ratings 서비스를 들어가면 istio config가 설정된 것이 확인된다.
그러나 트레이스로 확인해도, 지표로 확인해도 503 트래픽에 대한 재시도는 발생하지 않았다.

혹시나 parentRef 필드가 의미하는 것이 요청을 보내는 측의 워크로드들을 의미하는 건가 싶어 reviews 쪽에도 route 리소스를 만들어보았지만 아무런 변화가 발생하지 않았다.
할 수 있는 것은 모두 시도해봤다고 생각했는데, 도저히 해결이 되지 않아 이스티오 설정과 충돌하는 게 있을 수도 있겠다고 추측만 하고 실습은 종료했다.

for i in {1..500}; do curl http://localhost:8080/api/v1/products/1/reviews -s | jq -r '.podname as $p | .reviews[0] | "\($p) \(.rating)"' ; done | sort | uniq -c | sort -nr

image.png
추가적으로 이스티오의 데이터 플레인이 활성화되지 않은 네임스페이스에서 테스트도 진행해보았으나, 동작하지 않았다.
gateway api를 구현하는 측은 밑단의 istio여야만 하므로, 사실 이런 방식 자체가 말이 안되는 것 같기는 하다.
이렇게도 세팅하면서 짐작하게 된 부분 중 하나는, GAMMA 프로젝트가 왜 출범했는지에 대한 부분이다.
이스티오와 같은 서비스 메시가 관리하는 네임스페이스와 그렇지 않은 네임스페이스 간 설정에서 gateway api를 활용하기 위한 것이 애초에 주목적이었던 게 아닐까?
(라고 생각은 드는데, 해도 안 되던데?)
이미 서비스 메시를 적용한 네임스페이스에 대해 구태여 gateway api를 통해 인 클러스터 트래픽을 관리하려는 것 자체가 이상한 접근이라고도 생각이 든다.
만약 이 생각이 맞다면, 이스티오의 모든 리소스를 대체할 수 있는 리소스로서 gateway api가 존재한다고 생각했던 내 생각은 완벽히 틀린 것이다.
gateway api는 인그레스를 대체하기 위해 나온 리소스이고, 이를 위한 기능 개발에만 초점이 맞춰져 있는 것이라고 한다면 현 실습 방향이 잘못됐다는 것으로 명쾌하게 이해되기는 한다.
그러나 개인적으로 또 한가지 드는 생각은, 이럴 거면 뭐하러 게이트웨이 api를 쓰는가? 하는 것이다.
대부분의 서비스 메시가 이미 인그레스와 이그레스에 대한 기능을 제공하고 있으니, gateway api는 구태여 서비스 메시를 활용하는 환경에서는 효용이 없는 리소스이다.
그렇다면 인그레스 리소스를 대체하는 리소스로서는 적합한가?
인그레스는 설정할 포트가 고정된다던가, 상세한 설정은 전부 어노테이션을 통해 세팅해야 한다던가 하는 불편한 리소스였던 것은 분명하다.
그러나 이를 대체하기 위해 나온 게이트웨이 api는, 내가 느끼기엔 되려 너무 거창한 것처럼 보인다.
인그레스만 대체한답시고 개발된 것 치고는, 쿠버의 RBAC를 준수하면서 3 부류의 페르소나를 위해 각기 설정을 한 리소스를 분리하고, 네임스페이스 간 연동 설정을 지원하는 등 지나치게 오버엔지니어링된 것이 아닌가 하는 느낌을 지울 수가 없다.
물론 이건 인그레스의 단점을 위에 내가 언급한 부분에만 초점을 맞췄을 때 그렇다는 것이다.
내가 명쾌하게 짚지 않은, 인그레스가 가진 한계와 단점을 먼저 정리하고 이 부분을 다시 고찰해봐야 할 것 같다.

에러율 줄이기 - 두번째 시도

image.png
클러스터를 껐다 키고 난 이후, 로그를 다시 살펴보는데 retry가 이뤄지는 것이 확인됐다.
이전 클러스터에서 제대로 이 부분을 확인하지 않았기 때문에, 클러스터를 재구축하면서 재시도 로직이 적용됐다고 보기는 어렵다.
근데 200 떠도 왜 죄다 retry라 써있는 지는.. 모르겠지만, 메트릭을 확인해보니 실제로 에러율이 줄어드는 것이 확인됐다.
image.png
이전에도 제대로 되고 있었나 하는 생각이 잠시 스쳤는데, 그건 확실히 아니라고 판단했다.
왜냐하면 이전에는 트레이싱을 확인했을 때 무조건 span이 8개로 추가 재시도하는 트레이스가 보이지 않았기 때문이다.
지금 제대로 세팅된 상태에서는 확실하게 재시도되는 것까지 트레이스로 확인된다.
이번 클러스터가 저번 클러스터와 비교해서 달라진 게 하나도 없는 게, 그냥 이전에 쓰던 세팅 그대로 적용했다..
설정들을 적용하는 순서에 따라 차이가 있었을 수도 있겠다는 생각이 드는데, 아직 잘 모르는 입장에서는 그냥 내가 잘못한 게 있지 않을까 하는 방향으로 먼저 결론을 내릴까 한다.
순서 때문에 문제가 됐다면 개인적으로는 이스티오 시스템의 안정성을 의심해야 할 것 같기 때문이다.
image.png
이상한 게 또 있는데, 이번에는 gateway api의 리소스를 추적하지 않고 있다.
이전하고 정말 달랐던 게 뭐지..?

apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
  name: mesh-default
  namespace: istio-system
spec:
  metrics:
    - overrides:
        - match:
            metric: ALL_METRICS
            mode: SERVER
          disabled: true
  tracing:
  - providers:
    - name: jaeger

키알리 대시보드에서 재시도를 반영한 에러율이 제대로 추적되지 않는 문제가 껄끄러워서 텔레메트리 api 관련 문서를 조금 더 찾아보았다.
이때 확인할 수 있었던 것이, 기본적으로 이스티오의 메트릭은 내부 서비스 간 통신에서 서버(요청을 받은 쪽)와 클라(요청을 보낸 쪽)의 메트릭을 전부 수집한다는 것이었다.
재시도 관련 설정은 서버 측에 하는 것이고 이를 기반으로 클라의 엔보이가 재시도를 하는 것이기 때문에, 서버 측의 메트릭을 비활성화하면 의도한 대로 에러율을 시각화할 수 있지 않을까 하여 위와 같이 설정했다.
image.png
허허.. 드디어 의도한 대로 시각화까지 되는 것을 확인할 수 있었다.
image.png
현 설정에서는 에러율이 10퍼센트 이상일 때 그래프가 빨간색으로 표시되므로, 이제야 제대로 시각화된다고 볼 수 있겠다.

결론

이번 주차는 간단하게 실습을 하는 게 목적이라 상세 분석은 진행하지 않았다(그런 것 치고는 꽤 많이 판 것 같긴 하지만).
다만 gateway api와 기존 이스티오의 리소스를 간단하게 비교하자면..[9]

사용성은 어떠한가?
일단 설정 방식 자체는 대체로 비슷해서 엄청난 차이가 느껴지진 않았다.
다만 이스티오의 리소스는 이스티오 컨트롤 플레인과 잘 결합되어 설정이 잘 되는 편이다.
그러나 게이트웨이 api는 통신 간 암호화를 위해서는 추가적인 설정을 필요로 한다던가 하는 별도의 설정들이 더 필요한 편이다.

게이트웨이 api는 쿠버의 공식 api로 결합되었기에, 서비스 메시를 사용하지 않는 조직에서 인그레스를 대체하기 위한 용도로 사용하기에는 꽤나 유용하다.
인그레스는 앞으로도 업데이트가 되지 않을 예정이기에 궁극적으로 게이트웨이 api를 사용하는 방향으로 가는 것은 기술 부채로부터 상대적으로 안전하다.
앞으로 기능 개발과 문서화가 더 이뤄져서 성숙도가 높아진다면 완전히 서비스 메시 설정 리소스로서 활용하기에도 좋을 것이라 생각한다.

그나저나 아까 내가 이해를 잘못해서 설정이 잘못됐나 한참 헤매느라 진땀 뺐다..

쿠버 네이티브 사이드카 컨테이너로 프록시 배포

쿠버네티스 최신 버전에서는 사이드카 컨테이너 기능을 제공한다.
자세한 건 해당 문서를 참고하고, 간단하게만 요약하자면 앱 컨테이너와 명확하게 라이프사이클을 함께하는 것이 보장되도록 사이드카 컨테이너를 설정할 수 있도록 하는 기능이 추가된 것이다.
방법은 초기화 컨테이너에 사이드카로 삼으려는 컨테이너를 설정하되, 재시작 정책을 Always로 두는 것이다.
이렇게 하면 앱 컨테이너 실행 전 종료되는 것이 보장돼야 하는 초기화 컨테이너가 아닌, 앱 컨테이너보다 먼저 실행되면서 파드가 종료될 때 종료되는 것이 보장되는 갓벽한 라이프사이클의 컨테이너로서 기능하게 된다!

이스티오에서도 이 사이드카를 그대로 사용할 수 있다.[10]

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  profile: demo
  components:
    ingressGateways:
    - name: istio-ingressgateway
      enabled: true
      k8s:
        service:
          type: NodePort
          ports:
          - port: 80
            targetPort: 8080
            nodePort: 30000
          externalTrafficPolicy: Local
    egressGateways:
    - name: istio-egressgateway
      enabled: false
  meshConfig:
    defaultProviders:
      metrics:
      - prometheus
      tracing: []
  values:
    pilot:
      env:
        ENABLE_NATIVE_SIDECARS: true

istio operator에서 헬름 values 파일에 넣는 설정을 넣는 필드가 있다.
여기에 values.pilot.env에 설정값을 넣어주면 된다.

istioctl upgrade -f initstio.yaml

업그레이드를 하고, 샘플 파일을 재기동 해준다.
image.png
기본 상태를 보면 별 차이가 없어보인다.
image.png
그러나 막상 container 부분에는 하나의 컨테이너만 띄워져 있는 것이 보인다!

Init Containers:
  istio-init:
    Image:         docker.io/istio/proxyv2:1.25.1
    ...
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Thu, 10 Apr 2025 19:16:39 +0900
      Finished:     Thu, 10 Apr 2025 19:16:39 +0900
    Ready:          True
    Restart Count:  0
  istio-proxy:
    Image:         docker.io/istio/proxyv2:1.25.1
    Port:          15090/TCP
    Host Port:     0/TCP
    Args:
      proxy
      sidecar
      --domain
      $(POD_NAMESPACE).svc.cluster.local
      --proxyLogLevel=warning
      --proxyComponentLogLevel=misc:error
      --log_output_level=default:info
    State:          Running
      Started:      Thu, 10 Apr 2025 19:16:40 +0900
    Ready:          True
    Readiness:  http-get http://:15021/healthz/ready delay=0s timeout=3s period=15s #success=1 #failure=4
    Startup:    http-get http://:15021/healthz/ready delay=0s timeout=3s period=1s #success=1 #failure=600
    ...

init container 쪽을 보면, 기존에 컨테이너 쪽에서 돌아가던 프록시 컨테이너가 들어있는 것을 볼 수 있다.
어디에 설정됐냐 해서 실제 동작에서 달라지는 것은 없다.
다만 이제 이 프록시는 명확하게 앱 컨테이너가 실행되기 이전에 실행되고, 종료될 때도 앱 컨테이너 종료 이후에 종료되는 것이 보장된다.
그래서 파드 실행 간에 미연의 오작동을 원천 봉쇄할 수 있게 된다.

막간 실험

실습을 하다가 두 가지를 실험해보고 싶어졌다.

이런 케이스에 대해서 당연히 검증 에러를 내뿜거나, 알아서 다른 포트를 설정하도록 자동화를 해두었을 것이라 생각하지만 그래도 궁금한 건 참을 수 없다.

apiVersion: v1
kind: Pod
metadata:
  name: bad-pod
  labels:
    role: bad-pod
spec:
  containers:
    - name: istio-proxy
      image: nginx:1.21
      imagePullPolicy: IfNotPresent
      ports:
        - containerPort: 80
          protocol: TCP
        - containerPort: 15001
          protocol: TCP

대놓고 멀쩡한 이스티오 데이터 플레인 설정을 괴롭히기 위해 컨테이너 이름과 포트를 점유하는 아주 못된 파드다.
image.png
음, Goland를 익히는 중인데 아직 익숙치 않아서 어떤 식으로 로깅을 해주고 있는 명확히는 모르겠다.
컨테이너 로그에다 이벤트 로그까지 한꺼번에 보여주고 있는 것 같은데, 이건 나중에 조금 더 파보기로 하고, 아무튼 문제가 발생한 상황을 볼 수 있다.
image.png
나는 당연히 istio-proxy라는 이름을 먼저 써버리면 승인 웹훅을 통해 검증 에러를 내줄 거라 생각했는데, 단순하게 변형 웹훅만 걸려있는 것으로 보인다.
image.png
원래는 내가 만든 컨테이너와 변형 웹훅을 통해 주입된 컨테이너로 2개의 컨테이너가 떠야 정상이나, 내 예상과 다르게 그냥 내가 설정한 컨테이너에 덮어씌우기를 시전했다;;
이스티오 일해라
사실 누가 컨테이너 이름을 istio-proxy로 하겠냐마는.. 검증 웹훅을 통해 휴먼 에러를 막는 로직이 있으면 좋겠다는 생각은 든다.

apiVersion: v1
kind: Pod
metadata:
  name: bad-pod
  labels:
    role: bad-pod
spec:
  containers:
    - name: istio
	  image:  docker.io/istio/proxyv2:1.25.1
      imagePullPolicy: IfNotPresent
      ports:
        - containerPort: 80
          protocol: TCP
        - containerPort: 15001
          protocol: TCP
        - containerPort: 15006
          protocol: TCP

이번에는 이름은 그대로 두고, 이미지를 아예 변경했다.
사실 파드 양식에 포트를 설정하는 것은 어차피 실제 프로세스에 아무런 영향을 주지 않는다.
그냥 클러스터 내에서 포트 매핑을 빠르게 하기 위해 가시성 작업에 지나지 않고, 끽해야 포트 이름 설정 정도.
사용되는 이미지가 해당 포트를 사용하고 있을 때만 같은 네트워크 상에서 포트가 바인딩됐다던가 하는 에러가 나올 것이다.
그래서 아예 주입되는 컨테이너 이미지를 내가 먼저 넣어봤다.
image.png
이번에도 에러가 발생한다.
이 에러는 뭔가 했는데, 그냥 단순히 인자를 전달하지 않고 이미지를 사용하여 컨테이너가 완료돼서 크룹백에 빠진 이슈였다.
image.png
초기화 컨테이너의 설정에는 아무런 변화가 발생하지 않았다.

istio-proxy라는 컨테이너 이름을 사용하는 실무 케이스는 절대 흔하지 않을 것이라 생각하고 그래서 저런 부분에 대한 이슈 대응이 크게 필요하지 않다고 생각한다.
그런데 포트는 조금 더 엄밀하게 제한을 둬야 하는 걸 필요성이 있지 않을까 싶기도 하다.
15001, 15006 포트가 well-known 포트마냥 전세계적으로 잘 알려진 이스티오 전용 포트라도 되는 건가?
설령 그렇다고 해도 해당 포트를 사용하는 어플리케이션이 있다면 이에 대한 경고나 에러를 사전에 띄우는 식으로라도 제한을 걸어둬야 디버깅에 도움이 될 것 같다.

아무튼 어거지로 이스티오 괴롭히기 실험이었지만, 생각보다 사이드카 설정이 경직돼있다는 것을 알 수 있었다..
아마 추후에 데이터 플레인 설정 방법을 조금 더 파다보면 이런 것들도 커스텀하는 방법이 있을지도 모르겠다.

스터디

1장과 2장을 할 것인데, 그냥 서비스메쉬 개념과 이스티오 맛보기

서비스 메쉬의 등장 배경
기술이 변하며 과거의 문제가 증가하는 경우 생김
네트워크 역시 어플리케이션의 고려 사항이 된다.
이때 애플리케이션이 모든 네트워크 처리를 해야 하나?
재시도, 타임아웃, 서킷 브레이커 같은 것의 네트워크 복원력을, 개발자가?

인프라 레벨에서 이것을 하기 위한 움직임으로 나오게 된 것이 서비스 메쉬
이로부터 얻은 ㄴ것.

이스티오
서비스 메쉬 구현체 중 하나.
앱 코드를 수정하지 않고도 보안, 정책 관리, 관측 가능성과 같은 어려운 문제를 해결할 수 있고, 신뢰성 있고 안전한 클라우드 네이티브 시스템 구축
이스티오를 사용하면 기존 시스템을 바꾸지 않고 애플리케이션 네트워킹 관심사를 구현할 수 잇따.

사용사례, acme
요청 처리 시간이 불규칙하고, 팀별 다른 보안 정책
클라우드 환경에서는 인프라가 일시적이고 간혹 사용할 수 없다는 가정 아래 아키텍쳐를 설계애햐 한다.
네트워크의 불확실성이 발생할 수 있다는 것이다.

애플리케이션 단에서 처리하는 것도 가능하다.
이를 애플리케이션 네트워킹이라고 부른다.
그러나, 이것은 언어 종속적이고, 인프라 환경에 대한 이해가 부족한 상태로 이뤄질 수 있다.

개발자는 비즈니스 로직을 만드는데 집중해야 하는데, 이것이 힘들어진다.
그래서 인프라 환경을 잘 알고 있는 운영팀이 아예 처음부터 이런 것들을 맡기 위한 시도가 바로 서비스 메시

어떻게 동작하냐?
프록시.
서비스에 오가는 모든 트래픽을 프록시가 가로채서 진행한다.
이를 서비스 프록시라고 표현하며, L7 단계에서 동작한다.
이스티오에서는 Envoy를 선택한다.

엔보이는 api로 동적 관리도 가능
재시도, 타임아웃, 서킷 브레이커등 다양한 기능을 이미 다 가지고 있다.
그래서 이 친구가 데이터 플레인의 핵심이 됏다.

프메 메트릭 수집하는 것도, 이제 개발팀한테 메트릭 경로 제공하라고 이야기할 필요도 없이 그냥 엔보이에 설정하면 끝.

서비스메쉬
이스티오는 분산형이다.
프록시가 앱마다 배포되기 때문에 이리 부른다.
컨트롤 플레인과 데이터 플레인.
istiod가 컨플

이스티오는 돛을 의미한다.
vm 서버들을 이스티오에 엮어서 관리하는 것도 8주차에 볼 것이다.

서비스의 진입점이 이스티오 게이트웨이.
이것도 엔보이.
한번에 관리할 수 있다는 게 정말 좋다.
mltls도 쉽게 할 수 있게 되니.

서비스메시와 api 게이트웨이 차이.
게위는 앞단의 위치한 놈.
이 놈이 모든 트래픽을 담당한다.
내부 트래픽도 중앙 집중형.
서비스메시는 각각이 알아서 통신.
프록시로 이게 다 된다.

이스티오를 넣기 적합한 겨우.
앺 단이 복잡한 경우.
언어도 많고 팀도 맣고.
그래서 인프라에서 네트워크 기능을 담당하게 할 때.
이스티오는 어떤 비즈니스로직도 구현하거나 대체하지 않는다.

엔보이의 설정 api는 xds라 부른다.
lds, rds, cds, eds

우리는 1.23.17
이스티오는 1.17

kind create cluster --name myk8s --image kindest/node:v1.32.2 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30000
    hostPort: 30000
  - containerPort: 30001
    hostPort: 30001
  - containerPort: 30002
    hostPort: 30002
  - containerPort: 30003
    hostPort: 30003
  kubeadmConfigPatches:
  - |
    kind: ClusterConfiguration
    controllerManager:
      extraArgs:
        bind-address: "0.0.0.0"
    etcd:
      local:
        extraArgs:
          listen-metrics-urls: "http://0.0.0.0:2381"
    scheduler:
      extraArgs:
        bind-address: "0.0.0.0"
  - |
    kind: KubeProxyConfiguration
    metricsBindAddress: "0.0.0.0"
EOF
git clone https://github.com/AcornPublishing/istio-in-action
cd istio-in-action/book-source-code-master
pwd
code .

kind create cluster --name myk8s --image kindest/node:v1.23.17 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30000 # Sample Application
    hostPort: 30000
  - containerPort: 30001 # Prometheus
    hostPort: 30001
  - containerPort: 30002 # Grafana
    hostPort: 30002
  - containerPort: 30003 # Kiali
    hostPort: 30003
  - containerPort: 30004 # Tracing
    hostPort: 30004
  - containerPort: 30005 # kube-ops-view
    hostPort: 30005
  extraMounts:
  - hostPath: ${pwd}
    containerPath: /istiobook
networking:
  podSubnet: 10.10.0.0/16
  serviceSubnet: 10.200.1.0/24
EOF

# 설치 확인
docker ps

# 노드에 기본 툴 설치
docker exec -it myk8s-control-plane sh -c 'apt update && apt install tree psmisc lsof wget bridge-utils net-tools dnsutils tcpdump ngrep iputils-ping git vim -y'

helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set service.main.type=NodePort,service.main.ports.http.nodePort=30005 --set env.TZ="Asia/Seoul" --namespace kube-system
kubectl get deploy,pod,svc,ep -n kube-system -l app.kubernetes.io/instance=kube-ops-view

## kube-ops-view 접속 URL 확인
open "http://localhost:30005/#scale=1.5"
open "http://localhost:30005/#scale=1.3"

# (옵션) metrics-server
helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/
helm install metrics-server metrics-server/metrics-server --set 'args[0]=--kubelet-insecure-tls' -n kube-system
kubectl get all -n kube-system -l app.kubernetes.io/instance=metrics-server

image.png
트레이싱도할 건데, 집킨 기준

관련 문서

이름 noteType created
25.05 테크니컬 라이팅 area 2025-05-07
Envoy knowledge 2025-04-07
Istio Telemetry knowledge 2025-04-08
Istio Gateway knowledge 2025-04-16
Istio ServiceEntry knowledge 2025-04-17
Istio VirtualService knowledge 2025-04-21
Istio DestinationRule knowledge 2025-04-21
Istio EnvoyFilter knowledge 2025-04-21
Istio WasmPlugin knowledge 2025-04-21
아르고 롤아웃과 이스티오 연계 knowledge 2025-04-22
pilot-agent knowledge 2025-04-28
Kiali knowledge 2025-04-28
Istio PeerAuthentication knowledge 2025-05-04
Istio RequestAuthentication knowledge 2025-05-04
Istio AuthorizationPolicy knowledge 2025-05-04
Istio Operator knowledge 2025-05-09
istioctl knowledge 2025-05-12
Istio Sidecar knowledge 2025-05-13
Istio ProxyConfig knowledge 2025-05-17
istiod knowledge 2025-05-18
사이드카 모드 knowledge 2025-05-18
메시 배포 모델 knowledge 2025-05-21
Istio WorkloadGroup knowledge 2025-05-26
Istio WorkloadEntry knowledge 2025-05-26
앰비언트 모드 knowledge 2025-06-02
책 내용 정리 project 2025-04-03
스터디 내용 사전 정리 project 2025-04-03
1주차 - istio 소개, 첫걸음 project 2025-04-06
2주차 - 엔보이, 게이트웨이 project 2025-04-13
3주차 - 트래픽 관리 project 2025-04-19
3주차 - 네트워크 복원력 project 2025-04-23
4주차 - 이스티오 관측가능성 project 2025-04-27
5주차 - 통신 보안 project 2025-05-04
6주차 - 디버깅 project 2025-05-11
7주차 - 스케일링, 멀티 클러스터 project 2025-05-18
1W - 서비스 메시와 이스티오 published 2025-04-10
1W - 간단한 장애 상황 구현 후 대응 실습 published 2025-04-10
1W - Gateway API를 활용한 설정 published 2025-04-10
1W - 네이티브 사이드카 컨테이너 이용 published 2025-04-10
2W - 인그레스 게이트웨이 실습 published 2025-04-17
2W - 엔보이 published 2025-04-19
3W - 버츄얼 서비스를 활용한 기본 트래픽 관리 published 2025-04-22
3W - 트래픽 가중치 - flagger와 argo rollout을 이용한 점진적 배포 published 2025-04-22
3W - 트래픽 미러링 패킷 캡쳐 published 2025-04-22
3W - 서비스 엔트리와 이그레스 게이트웨이 published 2025-04-22
3W - 데스티네이션 룰을 활용한 네트워크 복원력 published 2025-04-26
3W - 타임아웃, 재시도를 활용한 네트워크 복원력 published 2025-04-26
4W - 이스티오 메트릭 확인 published 2025-05-03
4W - 이스티오 메트릭 커스텀, 프로메테우스와 그라파나 published 2025-05-03
4W - 번외 - 트레이싱용 심플 메시 서버 개발 published 2025-05-03
4W - 오픈텔레메트리 기반 트레이싱 예거 시각화, 키알리 시각화 published 2025-05-03
5W - 이스티오 mTLS와 SPIFFE published 2025-05-11
5W - 이스티오 JWT 인증 published 2025-05-11
5W - 이스티오 인가 정책 설정 published 2025-05-11
6W - 이스티오 설정 트러블슈팅 published 2025-05-18
6W - 이스티오 컨트롤 플레인 성능 최적화 published 2025-05-18
8W - 가상머신 통합하기 published 2025-06-01
8W - 엔보이와 iptables 뜯어먹기 published 2025-06-01
9W - 앰비언트 모드 구조, 원리 published 2025-06-07
9W - 앰비언트 헬름 설치, 각종 리소스 실습 published 2025-06-07
7W - 이스티오 메시 스케일링 published 2025-06-09
7W - 엔보이 필터를 통한 기능 확장 published 2025-06-09
이스티오 스케일링 topic 2025-05-18
엔보이에 와즘 플러그인 적용해보기 topic 2025-06-09
E-이스티오 설정 트러블슈팅하기 topic/explain 2025-05-18
E-이스티오 컨트롤 플레인 성능 최적화 topic/explain 2025-05-18
E-이스티오 컨트롤 플레인 메트릭 topic/explain 2025-05-18
E-이스티오의 데이터 플레인 트래픽 세팅 원리 topic/explain 2025-05-27
E-deb 파일 뜯어보기 topic/explain 2025-06-01
E-이스티오 DNS 프록시 동작 topic/explain 2025-06-01
E-이스티오 가상머신 통합 topic/explain 2025-06-01
E-이스티오에서 엔보이 기능 확장하기 topic/explain 2025-06-01
E-앰비언트 모드 헬름 세팅 topic/explain 2025-06-03
E-앰비언트 ztunnel 트래픽 경로 분석 topic/explain 2025-06-07
E-앰비언트 모드에서 메시 기능 활용 topic/explain 2025-06-07
E-이스티오 메시 스케일링 topic/explain 2025-06-08
E-istio-csr 사용 실습 topic/explain 2025-06-09
I-다른 네임스페이스 같은 포트 리스닝 서버 구현 topic/idea 2025-06-07
I-ztunnel이 다른 네임스페이스에서 요청 보내는 코드 분석 topic/idea 2025-06-07
T-엔보이 실습 with solo.io topic/temp 2025-04-14

참고


  1. https://istio.io/latest/docs/releases/supported-releases/ ↩︎

  2. https://kiali.io/docs/configuration/p8s-jaeger-grafana/tracing/jaeger/ ↩︎

  3. https://istio.io/latest/docs/tasks/observability/distributed-tracing/jaeger/ ↩︎

  4. https://github.com/istio/istio/blob/master/samples/addons/kiali.yaml ↩︎

  5. https://github.com/istio/istio/tree/master/samples/bookinfo/src ↩︎

  6. https://istio.io/latest/docs/setup/getting-started/#gateway-api ↩︎

  7. https://gateway-api.sigs.k8s.io/guides/#install-experimental-channel ↩︎

  8. https://gateway-api.sigs.k8s.io/mesh/gamma/ ↩︎

  9. https://istio.io/latest/docs/tasks/traffic-management/ingress/gateway-api/ ↩︎

  10. https://istio.io/latest/blog/2023/native-sidecars/ ↩︎